﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Xml.Serialization;
using T4UtilityBelt.DataDesigns;
using T4UtilityBelt.Serializers;
using T4UtilityBelt.UxDesigns.Bindings;
using T4UtilityBelt.UxDesigns.Controls;
using T4UtilityBelt.UxDesigns.Controls.Renderers;
using T4UtilityBelt.UxDesigns.Interfaces;


using T4UtilityBelt.Writers;

namespace T4UtilityBelt.UxDesigns
{
    [XDefaultProperty("Controls")]
    public abstract class Control
        : ContentElement, IControl
    {
        protected Control()
        {
            HorizontalAlignment = HorizontalAlignment.Stretch;
            VerticalAlignment = UxDesigns.VerticalAlignment.Stretch;
        }

        #region Properties

        private ControlCollection _controls;
        public ControlCollection Controls
        {
            get { return _controls ?? (_controls = new ControlCollection()); }
            //set { _controls = value; }
        }

        public bool HasControls
        {
            get
            {
                return _controls != null;
            }
        }

        public virtual string Uid { get; set; }

        public Binding DataContext { get; set; }

        public virtual string Style { get; set; }

        public virtual string Namespace { get; set; }

        public virtual string Name { get; set; }

        //public virtual string HelpText { get; set; }

        public int? GridRow { get; set; }

        public int? GridRowSpan { get; set; }

        public int? GridColumn { get; set; }

        public int? GridColumnSpan { get; set; }

        public Double? Height { get; set; }

        public Double? Width { get; set; }

        [DefaultValue(VerticalAlignment.Stretch)]
        public VerticalAlignment VerticalAlignment { get; set; }

        [DefaultValue(HorizontalAlignment.Stretch)]
        public HorizontalAlignment HorizontalAlignment { get; set; }

        //public string IsEnabledProperty { get; set; }

        //public string IsVisibleProperty { get; set; }

        #endregion Properties

        #region Methods

        public static Control Create(Property property)
        {
            return property.CreateControl();
        }

        public virtual IEnumerable<Control> AllControls()
        {
            if (HasControls)
            {
                foreach (var c in Controls)
                {
                    yield return c;
                    foreach (Control cc in c.AllControls())
                    {
                        yield return cc;
                    }
                }
            }
        }

        #endregion Methods
    }

    public abstract class Control<TControl, TRenderer> : Control
        where TControl : Control<TControl, TRenderer>
        where TRenderer : class, IControlRenderer<TControl, TRenderer>
    {
        #region Rendering

        protected TRenderer CreateControlRenderer(Platforms platform)
        {
            return RendererHelper.CreateRenderer<TRenderer>(platform);
        }

        #endregion Rendering

        #region Methods

        public override void FixModel(Entity entity)
        {
            foreach (IControl c in Controls)
            {
                c.FixModel(entity);
            }
        }

        public sealed override void RenderViewModelCs(CodeWriter writer)
        {
            CreateControlRenderer(writer.Platform).RenderUiCode(this as TControl, writer);
        }

        public sealed override void RenderUiXml(CodeWriter writer)
        {
            CreateControlRenderer(writer.Platform).RenderUiXml(this as TControl, writer);
        }

        public void RenderUiXmlBegin(CodeWriter writer)
        {
            CreateControlRenderer(writer.Platform).RenderUiXmlBegin(this as TControl, writer);
        }

        public void RenderUiXmlEnd(CodeWriter writer)
        {
            CreateControlRenderer(writer.Platform).RenderUiXmlEnd(this as TControl, writer);
        }

        #endregion Methods
    }
}